<?php
/*
*  Twi-Status 0.1b
*  Shows your status on Twitter
*  Author: Vladislav Samsonov (aka VladX)
*  GNU General Public License v2
*/

$user = preg_replace('#[^-a-zA-Z0-9_]#', '', $_GET['user']);
$id = $_GET['id'] + 1 - 1;
$query = 'count=1';
if (!$user)
	$user = 'habr_online';

if ($id)
	$query .= '&max_id=' . $id;

define('_USER_', $user);
define('_URL_', 'http://twitter.com/statuses/user_timeline/' . _USER_ . '.xml?' . $query);

$modes = array(
	'd' => array(
		'image' => 'shared/pattern_d.png',
		'size_x' => 350,
		'size_y' => 60,
		'header_pos_x' => 23,
		'header_pos_y' => 14,
		'text_pos_x' => 4,
		'text_pos_y' => 30,
		'header_format' => '%s   %s',
		'text_width' => 63
		),
	't' => array(
		'image' => 'shared/pattern_t.png',
		'size_x' => 150,
		'size_y' => 160,
		'header_pos_x' => 23,
		'header_pos_y' => 14,
		'text_pos_x' => 10,
		'text_pos_y' => 44,
		'header_format' => "%s\n  %s",
		'text_width' => 22
		),
	'u' => array(
		'image' => 'shared/pattern_u.png',
		'size_x' => 350,
		'size_y' => 20,
		'header_pos_x' => 23,
		'header_pos_y' => 14,
		'text_pos_x' => 23,
		'text_pos_y' => 14,
		'header_format' => '',
		'text_width' => 100
		),
);


class twiStatus
{
	public $name;
	public $date;
	public $text;
	public $text_color;
	public $header_text_color;
	public $background_color;
	
	private $xml;
	private $three;
	private $cached = false;
	
	function twiStatus()
	{
		$this->cache();
		$this->parseXmlToArray();
		$this->setName();
		$this->setDate();
		$this->setText();
		$this->setTextColor();
		$this->setHeaderTextColor();
		$this->setBackgroundColor();
		$this->setMode();
		if (!$this->cached)
			$this->cache(true);
		
		$this->image();
	}
	
	function setXml()
	{
		$this->xml = @file_get_contents(_URL_);
        if (!$this->xml)
            die('=((('); // That seems to be some error, probably, user doesn't exists
	}

    function setName()
    {
        $this->name = empty($this->three['name'][0]) ? _USER_ : $this->three['name'][0];
    }
    
    function setDate()
    {
        $this->date = date('d M G:i', strtotime($this->three['created_at'][0]));
    }
    
    function setText()
    {
        $this->text = empty($this->three['text'][0]) ? ';)' : $this->three['text'][0];
    }

    function setTextColor($default = '555555')
    {
        if ($_GET['text_color'] == 'inherit')
            $this->text_color = empty($this->three['profile_text_color'][0]) ? $default : $this->three['profile_text_color'][0];
        elseif (preg_match('#\#?[0-9a-f]{6}#i', $_GET['text_color']))
            $this->text_color = $_GET['text_color'];
        else
            $this->text_color = $default;
    }

    function setHeaderTextColor($default = '333333')
    {
        if ($_GET['header_text_color'] == 'inherit')
            $this->header_text_color = empty($this->three['profile_link_color'][0]) ? $default : $this->three['profile_link_color'][0];
        elseif (preg_match('#\#?[0-9a-f]{6}#i', $_GET['header_text_color']))
            $this->header_text_color = $_GET['header_text_color'];
        else
            $this->header_text_color = $default;

    }

    function setBackgroundColor($default = 'ffffff')
    {
        if ($_GET['background_color'] == 'inherit')
            $this->background_color = empty($this->three['profile_background_color'][0]) ? $default : $this->three['profile_background_color'][0];
        elseif (preg_match('#\#?[0-9a-f]{6}#i', $_GET['background_color']))
            $this->background_color = $_GET['background_color'];
        else
            $this->background_color = $default;
    }
	
	function setMode()
	{
		global $modes;
		$this->mode = isset($modes[$_GET['size']]) ? $modes[$_GET['size']] : $modes['d'];
		if ($_GET['size'] == 'u')
		{
			$this->text = $this->date . ' ' . $this->name . ': ' . $this->text;
			$this->text = mb_substr($this->text, 0, 54, 'utf-8') . '...';
		}
	}
	
	function parseXmlToArray()
	{
		if (!$this->xml)
			$this->setXml();
		
		$parser = new XMLReader();
		$parser->XML($this->xml);

		while ($parser->read())
		{/*
            if ($parser->depth == $lastDepth)
            {
                if (!isset($lastNode))
                {
                    $this->three[$parser->name] = $parser->value;
                    $lastNode = & $this->three[$parser->name];
                    $parentNode = & $this->three;
                }
                else
                {
                    $parentNode[$parser->name] = $parser->value;
                    $lastNode = & $parentNode[$parser->name];
                }
            }
            else
            {
                $lastNode[$parser->name] = $parser->value;
                $parentNode = & $lastNode;
                $lastNode = & $lastNode[$parser->name];
            }
            $lastDepth = $parser->depth;*/
            if ($parser->hasValue)
                $lastNode[] = $parser->value;
            else
            {
                if (!isset($this->three[$parser->name]))
                    $this->three[$parser->name] = '';
                    
                $lastNode = & $this->three[$parser->name];
            }
		}
		$parser->close();
	}
	
	function hex2rgb($color)
	{
		if ($color[0] == '#')
			$color = substr($color, 1);
		
		list($r, $g, $b) = array($color[0] . $color[1],
											$color[2] . $color[3],
											$color[4] . $color[5]);
		$r = hexdec($r);
		$g = hexdec($g);
		$b = hexdec($b);
		return array('r' => $r, 'g' => $g, 'b' => $b);
   }
   
   function utf8_wordwrap($str, $width = 75, $break = "\n") // wordwrap() with utf-8 support
   {
    	$str = preg_split('#[\s\n\r]+#', $str);
    	$len = 0;
    	foreach ($str as $val)
    	{
    		$val .= ' ';
    		$tmp = mb_strlen($val, 'utf-8');
    		$len += $tmp;
    		if ($len >= $width)
    		{
    			$return .= $break . $val;
    			$len = $tmp;
    		}
    		else
    			$return .= $val;
    	}
    	return $return;
	}
	
	function _hashed()
	{
		global $id;
		$this->setTextColor();
		$this->setHeaderTextColor();
		$this->setBackgroundColor();
		$this->setMode();
		return md5(_USER_ . $id . $this->text_color . $this->header_text_color . $this->background_color . $this->mode['image']) . '.png';
	}
	
	function image()
	{
		$background = @imagecreatetruecolor($this->mode['size_x'], $this->mode['size_y'])
			or die ('Cannot Initialize GD library');
		
		header('Content-type: image/png');
		$pattern = imagecreatefrompng($this->mode['image']);
		$text_color = $this->hex2rgb($this->text_color);
		$text_color = imagecolorallocate($background, $text_color['r'], $text_color['g'], $text_color['b']);
		$header_color = $this->hex2rgb($this->header_text_color);
		$header_color = imagecolorallocate($background, $header_color['r'], $header_color['g'], $header_color['b']);
		$background_color = $this->hex2rgb($this->background_color);
		$background_color = imagecolorallocate($background, $background_color['r'], $background_color['g'], $background_color['b']);
		imagefill($background, 0, 0, $background_color);
		imagecopy($background, $pattern, 0, 0, 0, 0,
			$this->mode['size_x'], $this->mode['size_y']);
		imagettftext($background, 8, 0, $this->mode['header_pos_x'],
			$this->mode['header_pos_y'], $header_color, 'shared/DejaVuSans-Bold.ttf',
			sprintf($this->mode['header_format'], $this->date, $this->name));
		imagettftext($background, 8, 0, $this->mode['text_pos_x'],
			$this->mode['text_pos_y'], $text_color, 'shared/DejaVuSansCondensed.ttf',
			$this->utf8_wordwrap($this->text, $this->mode['text_width']));
		$img_path = 'cached_images/' . $this->_hashed();
		imagepng($background, $img_path);
		touch($img_path);
		echo file_get_contents($img_path);
		imagedestroy($pattern);
		imagedestroy($background);
	}
	
	function cache($force = false)
	{
		if (($_GET['text_color'] == 'inherit' || $_GET['header_text_color'] == 'inherit' || $_GET['background_color'] == 'inherit') && !$force)
			return;
			
		$this->cached = true;
		
		if (!is_file('last_clear'))
			touch('last_clear');
		
		if (time() - filemtime('last_clear') > 48*60*60)
		{
			$dir = opendir('cached_images');
			while ($file = readdir($dir))
			{
				if(is_file('cached_images/'.$file) && (time() - filemtime('cached_images/'.$file) > 48*60*60))
				{
					unlink('cached_images/'.$file);
				}
			}
			touch('last_clear');
			closedir($dir);
		}
		$img_path = 'cached_images/' . $this->_hashed();
		if (is_file($img_path) && time() - filemtime($img_path) < 900)
		{
			header('Content-type: image/png');
			header('Cache-Control: no-cache, must-revalidate'); 
			header('Pragma: no-cache'); 
			echo file_get_contents($img_path);
			exit;
		}
	}
}

new twiStatus;
?>
